home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/python
- # Copyright (c) 2003 CORE Security Technologies
- #
- # This software is provided under under a slightly modified version
- # of the Apache Software License. See the accompanying LICENSE file
- # for more information.
- #
- # $Id: rpcdump.py,v 1.2 2003/10/28 21:02:20 jkohen Exp $
- #
- # DCE/RPC endpoint mapper dumper.
- #
- # Author:
- # Javier Kohen <jkohen@coresecurity.com>
- #
- # Reference for:
- # DCE/RPC.
-
- import socket
- import string
- import sys
- import types
-
- from impacket import uuid
- from impacket.dcerpc import dcerpc_v4, dcerpc, transport, epm
-
- class RPCDump:
- KNOWN_PROTOCOLS = {
- '139/SMB': (r'ncacn_np:%s[\pipe\epmapper]', 139),
- '445/SMB': (r'ncacn_np:%s[\pipe\epmapper]', 445),
- '135/TCP': (r'ncacn_ip_tcp:%s', 135),
- '135/UDP': (r'ncadg_ip_udp:%s', 135),
- '80/HTTP': (r'ncacn_http:%s', 80),
- }
-
-
- def __init__(self, protocols = None,
- username = '', password = ''):
- if not protocols:
- protocols = RPCDump.KNOWN_PROTOCOLS.keys()
-
- self.__username = username
- self.__password = password
- self.__protocols = protocols
-
-
- def dump(self, addr):
- """Dumps the list of endpoints registered with the mapper
- listening at addr. Addr is a valid host name or IP address in
- string format.
- """
-
- print 'Retrieving endpoint list from %s' % addr
-
- # Try all requested protocols until one works.
- entries = []
- for protocol in self.__protocols:
- protodef = RPCDump.KNOWN_PROTOCOLS[protocol]
- port = protodef[1]
-
- print "Trying protocol %s..." % protocol
- stringbinding = protodef[0] % addr
-
- rpctransport = transport.DCERPCTransportFactory(stringbinding)
- rpctransport.set_dport(port)
- if hasattr(rpctransport, 'set_credentials'):
- # This method exists only for selected protocol sequences.
- rpctransport.set_credentials(self.__username, self.__password)
-
- try:
- entries = self.__fetchList(rpctransport)
- except Exception, e:
- print 'Protocol failed: %s' % e
- else:
- # Got a response. No need for further iterations.
- break
-
-
- # Display results.
-
- for entry in entries:
- base = entry.getUUID()
- if 'unknown' != entry.getProviderName():
- print base + '/Provider:', entry.getProviderName()
- print base + '/Version:', entry.getVersion()
- if entry.getAnnotation():
- print base + '/Annotation:', entry.getAnnotation()
-
- objbase = base
- if not entry.isZeroObjUUID():
- objbase += '/' + entry.getObjUUID()
-
- stringbinding = transport.DCERPCStringBindingCompose('', entry.getProtocol(), '', entry.getEndpoint())
- print objbase + '/StringBindings:', stringbinding
-
- if entries:
- num = len(entries)
- if 1 == num:
- print 'Received one endpoint.'
- else:
- print 'Received %d endpoints.' % num
- else:
- print 'No endpoints found.'
-
-
- def __fetchList(self, rpctransport):
- # UDP only works over DCE/RPC version 4.
- if isinstance(rpctransport, transport.UDPTransport):
- dce = dcerpc_v4.DCERPC_v4(rpctransport)
- else:
- dce = dcerpc.DCERPC_v5(rpctransport)
-
- entries = []
-
- dce.connect()
- dce.bind(epm.MSRPC_UUID_PORTMAP)
- rpcepm = epm.DCERPCEpm(dce)
-
- resp = rpcepm.portmap_dump()
- while resp.get_entries_num() != 0:
- rpc_handle = resp.get_handle()
- ndrentry = resp.get_entry().get_entry()
- sb = transport.DCERPCStringBinding(ndrentry.get_string_binding())
- entry = epm.EpmEntry(uuid.bin_to_string(ndrentry.get_uuid()),
- ndrentry.get_version(),
- ndrentry.get_annotation(),
- uuid.bin_to_string(ndrentry.get_objuuid()),
- sb.get_protocol_sequence(),
- sb.get_endpoint())
- entries.append(entry)
- ## print str(entry)
- resp = rpcepm.portmap_dump(rpc_handle)
-
- dce.disconnect()
-
- return entries
-
-
- # Process command-line arguments.
- if __name__ == '__main__':
- if len(sys.argv) <= 1:
- print "Usage: %s [username[:password]@]<address> [protocol list...]" % sys.argv[0]
- print "Available protocols: %s" % RPCDump.KNOWN_PROTOCOLS.keys()
- print "Username and password are only required for certain transports, eg. SMB."
- sys.exit(1)
-
- import re
-
- username, password, address = re.compile('(?:([^@:]*)(?::([^@]*))?@)?(.*)').match(sys.argv[1]).groups('')
-
- if len(sys.argv) > 2:
- dumper = RPCDump(sys.argv[2:], username, password)
- else:
- dumper = RPCDump(username = username, password = password)
- dumper.dump(address)
-